#include "validation.h";
#include <iostream>
#include <string>

Validation::Validation(){
	V vc;

	//set arglist
	argList.insert("Assign");
	argList.insert("Statement");
	argList.insert("Assignment");
	argList.insert("Stmt");
	argList.insert("Stmtlst");
	argList.insert("Procedure");
	argList.insert("Plus");
	argList.insert("Minus");
	argList.insert("Times");
	argList.insert("Variable");
	argList.insert("Prog_line");
	argList.insert("While");
	argList.insert("If");
	argList.insert("Call");
	argList.insert("Constant");

	//calls
	vc.relation="calls";
	vc.argNo=2;
	vc.arg1_type.insert("Procedure");
	vc.arg1_type.insert("Prog_line");
	vc.arg1_type.insert("Constant");
	vc.arg1_type.insert("String");
	vc.arg1_type.insert("Integer");
	vc.arg1_type.insert("CallProc");
	vc.arg1_type.insert("StmtLst");
	vc.arg1_type.insert("Statement");
	vc.arg2_type.insert("Procedure");
	vc.arg2_type.insert("Prog_line");
	vc.arg2_type.insert("Constant");
	vc.arg2_type.insert("String");
	vc.arg2_type.insert("Integer");
	vc.arg2_type.insert("Statement");
	vc.arg2_type.insert("CallProc");
	vc.arg2_type.insert("StmtLst");
	vl.push_back(vc);

	//calls*
	vc.relation="calls*";
	vc.argNo=2;
	vc.arg1_type.insert("Procedure");
	vc.arg1_type.insert("Prog_line");
	vc.arg1_type.insert("Constant");
	vc.arg1_type.insert("String");
	vc.arg1_type.insert("Integer");
	vc.arg1_type.insert("CallProc");
	vc.arg1_type.insert("StmtLst");
	vc.arg1_type.insert("Statement");
	vc.arg2_type.insert("Procedure");
	vc.arg2_type.insert("Prog_line");
	vc.arg2_type.insert("Constant");
	vc.arg2_type.insert("string");
	vc.arg2_type.insert("integer");
	vc.arg2_type.insert("Statement");
	vc.arg2_type.insert("CallProc");
	vc.arg2_type.insert("StmtLst");
	vl.push_back(vc);

	//contains
	vc.relation="contains";
	vc.argNo=2;
	vc.arg1_type.insert("Procedure");
	vc.arg1_type.insert("Prog_line");
	vc.arg1_type.insert("Constant");
	vc.arg1_type.insert("String");
	vc.arg1_type.insert("Integer");
	vc.arg1_type.insert("Variable");
	vc.arg1_type.insert("If");
	vc.arg1_type.insert("While");
	vc.arg1_type.insert("+");
	vc.arg1_type.insert("-");
	vc.arg1_type.insert("*");
	vc.arg1_type.insert("StmtLst");
	vc.arg1_type.insert("Assign");
	vc.arg1_type.insert("CallProc");
	vc.arg1_type.insert("Statement");
	vc.arg2_type.insert("Procedure");
	vc.arg2_type.insert("Prog_line");
	vc.arg2_type.insert("Constant");
	vc.arg2_type.insert("String");
	vc.arg2_type.insert("Constant");
	vc.arg2_type.insert("Integer");
	vc.arg2_type.insert("+");
	vc.arg2_type.insert("-");
	vc.arg2_type.insert("*");
	vc.arg2_type.insert("CallProc");
	vc.arg2_type.insert("StmtLst");
	vc.arg2_type.insert("Variable");
	vc.arg2_type.insert("If");
	vc.arg2_type.insert("While");
	vc.arg2_type.insert("Assign");
	vl.push_back(vc);

	//contains
	vc.relation="contains*";
	vc.argNo=2;
	vc.arg1_type.insert("Procedure");
	vc.arg1_type.insert("Prog_line");
	vc.arg1_type.insert("Constant");
	vc.arg1_type.insert("String");
	vc.arg1_type.insert("Integer");
	vc.arg1_type.insert("+");
	vc.arg1_type.insert("-");
	vc.arg1_type.insert("*");
	vc.arg1_type.insert("Variable");
	vc.arg1_type.insert("If");
	vc.arg1_type.insert("While");
	vc.arg1_type.insert("StmtLst");
	vc.arg1_type.insert("Assign");
	vc.arg1_type.insert("Statement");
	vc.arg1_type.insert("CallProc");
	vc.arg2_type.insert("Procedure");
	vc.arg2_type.insert("Prog_line");
	vc.arg2_type.insert("Constant");
	vc.arg2_type.insert("String");
	vc.arg2_type.insert("Integer");
	vc.arg2_type.insert("Variable");
	vc.arg2_type.insert("If");
	vc.arg2_type.insert("While");
	vc.arg2_type.insert("Assign");
	vc.arg2_type.insert("+");
	vc.arg2_type.insert("-");
	vc.arg2_type.insert("*");
	vc.arg2_type.insert("CallProc");
	vc.arg2_type.insert("Constant");
	vc.arg2_type.insert("StmtLst");
	vl.push_back(vc);

	//modifies
	vc.relation="modifies";
	vc.argNo=2;
	vc.arg1_type.insert("Procedure");
	vc.arg1_type.insert("Prog_line");
	vc.arg1_type.insert("Statement");
	vc.arg1_type.insert("Assign");
	vc.arg1_type.insert("String");
	vc.arg1_type.insert("Integer");
	vc.arg1_type.insert("Call");
	vc.arg1_type.insert("While");
	vc.arg1_type.insert("Constant");
	vc.arg1_type.insert("StmtLst");
	vc.arg1_type.insert("If");
	vc.arg2_type.insert("Variable");
	vc.arg2_type.insert("Statement");
	vc.arg2_type.insert("StmtLst");
	vc.arg2_type.insert("String");
	vc.arg2_type.insert("Assign");
	vc.arg2_type.insert("Constant");
	vl.push_back(vc);

	//uses
	vc.relation="uses";
	vc.argNo=2;
	vc.arg1_type.insert("Procedure");
	vc.arg1_type.insert("Prog_line");
	vc.arg1_type.insert("Statement");
	vc.arg1_type.insert("Assign");
	vc.arg1_type.insert("String");
	vc.arg1_type.insert("Integer");
	vc.arg1_type.insert("Call");
	vc.arg1_type.insert("StmtLst");
	vc.arg1_type.insert("Constant");
	vc.arg1_type.insert("While");
	vc.arg1_type.insert("If");
	vc.arg2_type.insert("Variable");
	vc.arg2_type.insert("Statement");
	vc.arg2_type.insert("StmtLst");
	vc.arg2_type.insert("String");
	vc.arg2_type.insert("Constant");
	vl.push_back(vc);

	//follows
	vc.relation="follows";
	vc.argNo=2;
	vc.arg1_type.insert("Prog_line");
	vc.arg1_type.insert("Statement");
	vc.arg1_type.insert("Assign");
	vc.arg1_type.insert("Call");
	vc.arg1_type.insert("While");
	vc.arg1_type.insert("Constant");
	vc.arg1_type.insert("Integer");
	vc.arg1_type.insert("If");
	vc.arg2_type.insert("Prog_line");
	vc.arg2_type.insert("Statement");
	vc.arg2_type.insert("Assign");
	vc.arg2_type.insert("Call");
	vc.arg2_type.insert("While");
	vc.arg2_type.insert("Integer");
	vc.arg2_type.insert("If");
	vc.arg2_type.insert("Constant");
	vc.arg2_type.insert("StmtLst");
	vl.push_back(vc);

	//follows*
	vc.relation="follows*";
	vc.argNo=2;
	vc.arg1_type.insert("Prog_line");
	vc.arg1_type.insert("Statement");
	vc.arg1_type.insert("Assign");
	vc.arg1_type.insert("Call");
	vc.arg1_type.insert("While");
	vc.arg1_type.insert("Integer");
	vc.arg1_type.insert("If");
	vc.arg1_type.insert("Constant");
	vc.arg1_type.insert("StmtLst");
	vc.arg2_type.insert("Prog_line");
	vc.arg2_type.insert("Statement");
	vc.arg2_type.insert("Assign");
	vc.arg2_type.insert("Call");
	vc.arg2_type.insert("Integer");
	vc.arg2_type.insert("While");
	vc.arg2_type.insert("If");
	vc.arg2_type.insert("Constant");
	vc.arg2_type.insert("StmtLst");
	vl.push_back(vc);

	//next
	vc.relation="next";
	vc.argNo=2;
	vc.arg1_type.insert("Prog_line");
	vc.arg1_type.insert("Statement");
	vc.arg1_type.insert("Assign");
	vc.arg1_type.insert("Call");
	vc.arg1_type.insert("While");
	vc.arg1_type.insert("Integer");
	vc.arg1_type.insert("If");
	vc.arg1_type.insert("StmtLst");
	vc.arg1_type.insert("Constant");
	vc.arg2_type.insert("Prog_line");
	vc.arg2_type.insert("Statement");
	vc.arg2_type.insert("Assign");
	vc.arg2_type.insert("Call");
	vc.arg2_type.insert("Integer");
	vc.arg2_type.insert("While");
	vc.arg2_type.insert("If");
	vc.arg2_type.insert("StmtLst");
	vc.arg2_type.insert("Constant");
	vl.push_back(vc);

	//next*
	vc.relation="next*";
	vc.argNo=2;
	vc.arg1_type.insert("Prog_line");
	vc.arg1_type.insert("Statement");
	vc.arg1_type.insert("Assign");
	vc.arg1_type.insert("Call");
	vc.arg1_type.insert("While");
	vc.arg1_type.insert("Integer");
	vc.arg1_type.insert("If");
	vc.arg1_type.insert("StmtLst");
	vc.arg1_type.insert("Constant");
	vc.arg2_type.insert("Prog_line");
	vc.arg2_type.insert("Statement");
	vc.arg2_type.insert("Assign");
	vc.arg2_type.insert("Call");
	vc.arg2_type.insert("While");
	vc.arg2_type.insert("Integer");
	vc.arg2_type.insert("If");
	vc.arg2_type.insert("StmtLst");
	vc.arg2_type.insert("Constant");
	vl.push_back(vc);


	//nextbip
	vc.relation="nextbip";
	vc.argNo=2;
	vc.arg1_type.insert("Prog_line");
	vc.arg1_type.insert("Statement");
	vc.arg1_type.insert("Assign");
	vc.arg1_type.insert("Call");
	vc.arg1_type.insert("While");
	vc.arg1_type.insert("StmtLst");
	vc.arg1_type.insert("Integer");
	vc.arg1_type.insert("If");
	vc.arg1_type.insert("Constant");
	vc.arg2_type.insert("Prog_line");
	vc.arg2_type.insert("Statement");
	vc.arg2_type.insert("Assign");
	vc.arg2_type.insert("Call");
	vc.arg2_type.insert("While");
	vc.arg2_type.insert("Integer");
	vc.arg2_type.insert("If");
	vc.arg2_type.insert("StmtLst");
	vc.arg2_type.insert("Constant");
	vl.push_back(vc);

	//nextbip*
	vc.relation="nextbip*";
	vc.argNo=2;
	vc.arg1_type.insert("Prog_line");
	vc.arg1_type.insert("Statement");
	vc.arg1_type.insert("Assign");
	vc.arg1_type.insert("Call");
	vc.arg1_type.insert("While");
	vc.arg1_type.insert("Integer");
	vc.arg1_type.insert("If");
	vc.arg1_type.insert("StmtLst");
	vc.arg1_type.insert("Constant");
	vc.arg2_type.insert("Prog_line");
	vc.arg2_type.insert("Statement");
	vc.arg2_type.insert("Assign");
	vc.arg2_type.insert("Call");
	vc.arg2_type.insert("While");
	vc.arg2_type.insert("Integer");
	vc.arg2_type.insert("StmtLst");
	vc.arg2_type.insert("If");
	vc.arg2_type.insert("Constant");
	vl.push_back(vc);
	//affects
	vc.relation="affects";
	vc.argNo=2;
	vc.arg1_type.insert("Prog_line");
	vc.arg1_type.insert("Statement");
	vc.arg1_type.insert("Assign");
	vc.arg1_type.insert("Integer");
	vc.arg1_type.insert("Constant");
	vc.arg1_type.insert("StmtLst");
	vc.arg2_type.insert("Prog_line");
	vc.arg2_type.insert("Statement");
	vc.arg2_type.insert("Assign");
	vc.arg2_type.insert("Constant");
	vc.arg2_type.insert("StmtLst");
	vl.push_back(vc);

	//affects*
	vc.relation="affects*";
	vc.argNo=2;
	vc.arg1_type.insert("Prog_line");
	vc.arg1_type.insert("Statement");
	vc.arg1_type.insert("Assign");
	vc.arg1_type.insert("StmtLst");
	vc.arg1_type.insert("Integer");
	vc.arg1_type.insert("Constant");
	vc.arg2_type.insert("Prog_line");
	vc.arg2_type.insert("Statement");
	vc.arg2_type.insert("Assign");
	vc.arg2_type.insert("Constant");
	vc.arg2_type.insert("StmtLst");
	vl.push_back(vc);

	//affectsbip
	vc.relation="affectsbip";
	vc.argNo=2;
	vc.arg1_type.insert("Prog_line");
	vc.arg1_type.insert("Statement");
	vc.arg1_type.insert("Assign");
	vc.arg1_type.insert("StmtLst");
	vc.arg1_type.insert("Integer");
	vc.arg1_type.insert("Constant");
	vc.arg2_type.insert("Prog_line");
	vc.arg2_type.insert("Statement");
	vc.arg2_type.insert("Assign");
	vc.arg2_type.insert("Constant");
	vc.arg2_type.insert("StmtLst");
	vl.push_back(vc);

	//affectsbip*
	vc.relation="affectsbip*";
	vc.argNo=2;
	vc.arg1_type.insert("Prog_line");
	vc.arg1_type.insert("Statement");
	vc.arg1_type.insert("Assign");
	vc.arg1_type.insert("Integer");
	vc.arg1_type.insert("StmtLst");
	vc.arg1_type.insert("Constant");
	vc.arg2_type.insert("Prog_line");
	vc.arg2_type.insert("Statement");
	vc.arg2_type.insert("Assign");
	vc.arg2_type.insert("Constant");
	vc.arg2_type.insert("StmtLst");
	vl.push_back(vc);

	//parent
	vc.relation="parent";
	vc.argNo=2;
	vc.arg1_type.insert("Prog_line");
	vc.arg1_type.insert("Statement");
	vc.arg1_type.insert("Assign");
	vc.arg1_type.insert("While");
	vc.arg1_type.insert("Integer");
	vc.arg1_type.insert("If");
	vc.arg1_type.insert("Constant");
	vc.arg1_type.insert("StmtLst");
	vc.arg2_type.insert("Prog_line");
	vc.arg2_type.insert("Statement");
	vc.arg2_type.insert("Assign");
	vc.arg2_type.insert("While");
	vc.arg2_type.insert("Integer");
	vc.arg2_type.insert("If");
	vc.arg2_type.insert("StmtLst");
	vc.arg2_type.insert("Constant");
	vl.push_back(vc);

	//parent*
	vc.relation="parent*";
	vc.argNo=2;
	vc.arg1_type.insert("Prog_line");
	vc.arg1_type.insert("Statement");
	vc.arg1_type.insert("Assign");
	vc.arg1_type.insert("While");
	vc.arg1_type.insert("Integer");
	vc.arg1_type.insert("If");
	vc.arg1_type.insert("Constant");
	vc.arg1_type.insert("StmtLst");
	vc.arg2_type.insert("Prog_line");
	vc.arg2_type.insert("Statement");
	vc.arg2_type.insert("Assign");
	vc.arg2_type.insert("While");
	vc.arg2_type.insert("Integer");
	vc.arg2_type.insert("If");
	vc.arg2_type.insert("StmtLst");
	vc.arg2_type.insert("Constant");
	vl.push_back(vc);
};

bool Validation::check_func(string func_name, int argno, string arg1_type, string arg2_type){
	for(size_t i=0; i<vl.size(); i++){
		if(vl.at(i).relation==func_name){
			if(vl.at(i).argNo!=argno) return false;
			if(vl.at(i).arg1_type.find(arg1_type)==vl.at(i).arg1_type.end()) return false;
			if(vl.at(i).arg2_type.find(arg2_type)==vl.at(i).arg2_type.end()) return false;

			return true;
		}
	}
	return false;
};

bool Validation::check_with(string arg1_type,string arg1_attribute,string arg2_type, string arg2_attribute){
	
	if(arg1_attribute=="procName"&&(arg1_type!="Procedure"&&arg1_type!="Call"&&arg1_type!="CallProc")) return false;
	if(arg1_attribute=="varName"&&arg1_type!="Variable") return false;
	if(arg1_attribute=="value"&&arg1_type!="Constant") return false;
	//if(arg1_attribute=="stmt#"&&arg1_type!="Statement") return false;

	if(arg2_attribute=="procName"&&(arg2_type!="Procedure"&&arg2_type!="Call"&&arg2_type=="CallProc")) return false;
	if(arg2_attribute=="varName"&&arg2_type!="Variable") return false;
	if(arg2_attribute=="value"&&arg2_type!="Constant") return false;
	//if(arg2_attribute=="stmt#"&&arg2_type!="Statement") return false;

	string temp_left, temp_right;
	temp_left=""; temp_right="";
	if(arg1_type=="Procedure"||arg1_type=="Variable"||arg1_type=="CallProc"||arg1_type=="String"){
		temp_left="String";
	}else if(arg1_type=="Statement"||arg1_type=="Constant"||arg1_type=="Integer"||arg1_attribute=="value"||arg1_attribute=="stmt#"||(arg1_type!=""&&arg1_attribute=="")){
		temp_left="Integer";
	}else{
		temp_left=arg1_type;
	}
	
	if(arg2_type=="Procedure"||arg2_type=="Variable"||arg2_type=="CallProc"||arg2_type=="String"){
		temp_right="String";
	}else if(arg2_type=="Statement"||arg2_type=="Constant"||arg2_type=="Integer"||arg2_attribute=="value"||arg2_attribute=="stmt#"||(arg2_type!=""&&arg2_attribute=="")){
		temp_right="Integer";
	}else{
		temp_right=arg2_type;
	}
	if(temp_left!=temp_right) return false;

	return true;


};

bool Validation::check_pattern(string pattern_type, string arg1_type, string arg2_type){

	if(pattern_type!="Assign"&&pattern_type!="If"&&pattern_type!="While") return false;
	if(arg1_type!="_"&&arg1_type!="string"&&arg1_type!="variable") return false;
	if(arg2_type!="_"&&arg2_type!="string") return false;
	return true;
};

bool Validation::check_param_type(string paramType){
	if(argList.find(paramType)==argList.end()){
		return false;
	}
	return true;
};

bool Validation::check_select(string select){
	if(select!="select") return false;
	return true;
}

bool Validation::check_no_bool(string isbool){
	if(isbool=="BOOLEAN") return false;
	return true;
}

bool Validation::check_type_exist(string param){
	if(param=="") return false;
	return true;
}